﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace RainbowNavBar.Function
{
    public static class ApplicationConfig
    {
        /// <summary>
        /// 标签数据列表
        /// </summary>
        public static List<TagData> TagListData = new List<TagData>();

        //public static ObservableCollection<TagData> TagListData = new ObservableCollection<TagData>();

        /// <summary>
        /// 网址图标
        /// </summary>
        private readonly static BitmapImage UrlIcon = new(new Uri("pack://application:,,,/image/url.png"));
        private readonly static BitmapImage ApplyIcon = new(new Uri("pack://application:,,,/image/application.png"));

        /// <summary>
        /// 定义一个委托来回调通知方法
        /// </summary>
        public static Action<TagData> OnTagDataChanged;

        /// <summary>
        /// 配置文件地址
        /// </summary>
        public static string ConfigPath = GetConfigFilePath("RainbowNavBar.config");

        /// <summary>
        /// 创建 XmlConfigManager 实例
        /// </summary>
        public readonly static XmlConfigManager configManager = new(ConfigPath);

        /// <summary>
        /// 构造方法
        /// </summary>
        static ApplicationConfig()
        {
        }

        /// <summary>
        /// 获取配置文件地址
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static string GetConfigFilePath(string fileName)
        {
            // 获取用户的应用数据文件夹路径
#if WINDOWS_UWP
            // 对于UWP环境
            string folderPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "RainbowNavBar");
#else
            // 对于传统Win32/WPF环境
            string folderPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "RainbowNavBar");
#endif

            // 确保目录存在
            if (!System.IO.Directory.Exists(folderPath))
            {
                System.IO.Directory.CreateDirectory(folderPath);
            }

            // 返回完整的配置文件路径
            return System.IO.Path.Combine(folderPath, fileName);
        }

        /// <summary>
        /// 去除 BOM (读取文件方式)
        /// </summary>
        /// <param name="filePath">文件地址</param>
        public static void RemoveBomIfPresent(string filePath)
        {
            byte[] bom = { 0xEF, 0xBB, 0xBF }; // UTF-8 BOM
            byte[] fileBytes = File.ReadAllBytes(filePath);

            if (fileBytes.Length > 3 && fileBytes[0] == bom[0] && fileBytes[1] == bom[1] && fileBytes[2] == bom[2])
            {
                // 文件包含 BOM，移除并重写文件
                File.WriteAllBytes(filePath, fileBytes.Skip(3).ToArray());
            }
        }

        /// <summary>
        /// 去除BOM (byte)
        /// </summary>
        /// <param name="bt"></param>
        /// <returns></returns>
        public static byte[] RemoveBomIfPresent(byte[] bt)
        {
            byte[] bom = { 0xEF, 0xBB, 0xBF }; // UTF-8 BOM
            byte[] fileBytes = bt;

            if (fileBytes.Length > 3 && fileBytes[0] == bom[0] && fileBytes[1] == bom[1] && fileBytes[2] == bom[2])
            {
                // 文件包含 BOM，移除并重写文件
                return fileBytes.Skip(3).ToArray();
            }
            return bt;
        }


        #region 定义事件
        // 添加数据
        public static event Action<TagData> ItemAdded;
        // 删除数据
        public static event Action<TagData> ItemRemoved;
        // 更新数据
        public static event Action<TagData, string, Dictionary<string, string>> ItemUpdated;
        #endregion

        #region 数据触发

        /// <summary>
        /// 标签：添加数据
        /// </summary>
        /// <param name="td"></param>
        public static void TagAdd(TagData td, Dictionary<string, string> dic = null)
        {
            TagListData.Add(td);
            if (dic != null)
            {
                configManager.AddDataRecord(dic);
            }
            ItemAdded?.Invoke(td);
        }

        /// <summary>
        /// 标签：删除数据
        /// </summary>
        /// <param name="td"></param>
        public static void TagRemove(TagData td)
        {
            // 删除标签配置
            configManager.DeleteDataRecord(td.TagName);
            // 删除列表元素
            TagListData.Remove(td);
            ItemRemoved?.Invoke(td);
        }

        /// <summary>
        /// 标签：更新数据
        /// </summary>
        /// <param name="td"></param>
        /// <param name="tagName"></param>
        /// <param name="value"></param>
        public static void TagUpdated(TagData td, string tagName, Dictionary<string, string> value)
        {
            configManager.UpdateDataRecord(tagName, value);
            ItemUpdated?.Invoke(td, tagName, value);
        }

        /// <summary>
        /// 标签：清空数据
        /// </summary>
        public static void TagClear() { TagListData.Clear(); }

        /// <summary>
        /// 标签：自然排序
        /// </summary>
        public static void TagSorting()
        {
            TagListData.Sort((dict1, dict2) =>
            {
                // 获取 TagIndex 的值
                int tagIndex1 = int.TryParse(dict1.TagIndex.ToString(), out var result1) ? result1 : int.MaxValue;
                int tagIndex2 = int.TryParse(dict2.TagIndex.ToString(), out var result2) ? result2 : int.MaxValue;

                // 如果 TagIndex 为 -1, 将其排到后面
                if (tagIndex1 == -1 && tagIndex2 != -1) return 1;
                if (tagIndex2 == -1 && tagIndex1 != -1) return -1;

                // 其他情况按升序排序
                return tagIndex1.CompareTo(tagIndex2);
            });
        }

        #endregion

        #region 数据扩展

        /// <summary>
        /// 查询列表中的TagIndex是否存在该索引值
        /// </summary>
        /// <param name="tagIndex">编号索引值</param>
        /// <returns></returns>
        public static (bool, TagData) IsTagIndexExists(int tagIndex)
        {
            // 检查 TagListData 中是否有 TagIndex 等于指定值的 TagData
            var tag = TagListData.FirstOrDefault(t => t.TagIndex == tagIndex);

            if (tag != null)
            {
                // 如果找到，返回 true 和该元素的索引
                //int index = TagListData.IndexOf(tag);

                // 更新索引数据
                //tag.TagIndex = tagIndex;

                return (true, tag);
            }
            else
            {
                // 如果未找到，返回 false 和新的索引值
                return (false, null);
            }
        }

        #endregion

        #region 配置操作

        /// <summary>
        /// 文件是否存在
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static bool IsExist(string path)
        {
            return System.IO.File.Exists(path);
        }

        /// <summary>
        /// 提取嵌入程序内部的资源
        /// </summary>
        /// <param name="resourceName">资源名称（命名空间.资源名称）</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        private static string GetEmbeddedResourceContent(string resourceName)
        {
            // 获取当前执行程序的程序集
            var assembly = System.Reflection.Assembly.GetExecutingAssembly();

            // 获取资源流
            using (var stream = assembly.GetManifestResourceStream(resourceName))
            {
                if (stream == null)
                {
                    throw new Exception("未找到指定的嵌入资源：" + resourceName);
                }

                // 读取资源流中的内容
                using (var reader = new StreamReader(stream))
                {
                    return reader.ReadToEnd();
                }
            }
        }

        /// <summary>
        /// 创建配置文件
        /// </summary>
        /// <param name="path"></param>
        public static void CreateConfig(string path)
        {
            if (IsExist(path)) return;

            // 判断目标文件是否存在
            if (!File.Exists(path))
            {
                // 文件不存在，获取嵌入的资源文件 Q.xml 内容
                string xmlContent = GetEmbeddedResourceContent("RainbowNavBar.Q.xml");

                // 将内容写入到指定路径
                File.WriteAllText(path, xmlContent);

                Debug.WriteLine($"文件不存在，已将内容写入: {path}");
            }
            else
            {
                Debug.WriteLine("文件已存在，无需写入。");
            }
        }

        /// <summary>
        /// 获取XML文件中的数据
        /// </summary>
        public static void GetTagData()
        {
            // 获取所有的数据记录
            List<Dictionary<string, string>> dataRecords = configManager.GetAllDataRecords();
            if (dataRecords != null)
            {
                // 排序数据
                dataRecords.Sort((dict1, dict2) =>
                {
                    // 获取 TagIndex 的值
                    int tagIndex1 = int.TryParse(dict1["TagIndex"], out var result1) ? result1 : int.MaxValue;
                    int tagIndex2 = int.TryParse(dict2["TagIndex"], out var result2) ? result2 : int.MaxValue;

                    // 如果 TagIndex 为 -1, 将其排到后面
                    if (tagIndex1 == -1 && tagIndex2 != -1) return 1;
                    if (tagIndex2 == -1 && tagIndex1 != -1) return -1;

                    // 其他情况按升序排序
                    return tagIndex1.CompareTo(tagIndex2);
                });

                // 处理相同 TagIndex 的项，确保没有重复的 TagIndex
                //AdjustTagIndexes(ref dataRecords);

                // 添加标签到UI中
                foreach (var record in dataRecords)
                {
                    Label _label = new()
                    {
                        Width = 10,
                        Height = 30,
                        Content = record["TagName"],
                        Background = new SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString(record["TagColor"])),
                    };
                    TagAdd(new TagData()
                    {
                        TagIndex = Convert.ToInt32(record["TagIndex"]),
                        TagLabel = _label,
                        TagType = (FunType)Convert.ToInt32(record["TagType"]),
                        TagEnable = Convert.ToBoolean(record["TagEnable"]),
                        TagName = record["TagName"],
                        TagDescription = record["TagDescription"],
                        TagAddress = record["TagAddress"],
                        TagColor = (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString(record["TagColor"]),
                        TagColor_s = (Brush)new BrushConverter().ConvertFromString(record["TagColor"]),
                        //TagIcon = GetTypeIcon((FunType)Convert.ToInt32(record["TagType"])),                     
                        TagIcon = GetApplicationIconAsync(record["TagAddress"], (FunType)Convert.ToInt32(record["TagType"])),
                    });
                }
            }
        }

        /// <summary>
        /// 检测文本内容是否符合 XML 格式规则
        /// </summary>
        /// <param name="xmlContent">需要检查的 XML 内容</param>
        /// <returns>如果文本符合 XML 格式规则，返回 true；否则返回 false。</returns>
        public static bool IsValidXml(string xmlContent)
        {
            try
            {
                // 创建一个 XmlDocument 对象来加载 XML 内容
                XmlDocument doc = new();
                doc.LoadXml(xmlContent);  // 尝试加载 XML 内容
                return true;  // 没有异常，说明 XML 格式有效
            }
            catch (XmlException ex)
            {
                // 输出异常信息，帮助定位错误
                Debug.WriteLine($"XML 格式错误: {ex.Message}");
                Debug.WriteLine($"错误位置：行 {ex.LineNumber}, 列 {ex.LinePosition}");
                return false;  // 如果发生异常，说明 XML 格式无效
            }
        }

        /// <summary>
        /// 调整相同 TagIndex 的项，使其值唯一
        /// </summary>
        /// <param name="dataRecords"></param>
        public static void AdjustTagIndexes(ref List<Dictionary<string, string>> dataRecords)
        {
            for (int i = 0; i < dataRecords.Count - 1; i++)
            {
                // 获取当前记录的 TagIndex
                if (int.TryParse(dataRecords[i]["TagIndex"], out int tagIndex1) && tagIndex1 != -1)
                {
                    for (int j = i + 1; j < dataRecords.Count; j++)
                    {
                        if (int.TryParse(dataRecords[j]["TagIndex"], out int tagIndex2) && tagIndex2 == tagIndex1)
                        {
                            // 如果发现相同的 TagIndex，则修改第二项的 TagIndex
                            dataRecords[j]["TagIndex"] = (tagIndex1 + 1).ToString();
                            Debug.WriteLine(dataRecords[j]["TagIndex"]);
                            // 继续检查下一个记录
                            tagIndex1++;  // 递增当前的 TagIndex
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 数据格式转换
        /// </summary>
        /// <param name="funType"></param>
        /// <returns></returns>
        private static BitmapImage GetTypeIcon(FunType funType)
        {
            if (funType != FunType.APPLICATION)
            {
                return new BitmapImage(new Uri("pack://application:,,,/image/url.png"));
            }
            else
            {
                return new BitmapImage(new Uri("pack://application:,,,/image/application.png"));
            }
        }

        /// <summary>
        /// 获取应用程序的图标并显示在 Image 控件上
        /// </summary>
        /// <param name="exePath"></param>
        /// <param name="funType"></param>
        /// <returns></returns>
        public static BitmapImage GetApplicationIconAsync(string exePath, FunType funType)
        {
            if (funType != FunType.APPLICATION) return UrlIcon;

            #region 网络请求：获取网址图标(ICON)
            /***
            if (funType != FunType.APPLICATION)
            {
                BitmapImage bitmapImage = await GlobalFunction.GetFaviconAsync(exePath);
                if (bitmapImage == null)
                {
                    Debug.WriteLine("网址图标：Null: " + exePath);
                    return UrlIcon;
                }
                return bitmapImage;
            }
            ***/
            #endregion

            try
            {
                // 获取 exe 文件的图标
                System.Drawing.Icon appIcon = System.Drawing.Icon.ExtractAssociatedIcon(exePath);

                // 将 Icon 转换为 BitmapImage
                System.Windows.Media.Imaging.BitmapImage bitmapImage = ConvertIconToBitmapImage(appIcon);

                // 设置 Image 控件的 Source 为图标
                return bitmapImage;
            }
            catch (Exception ex)
            {
                Debug.WriteLine("无法获取图标: " + ex.Message);
                return ApplyIcon;
            }
        }

        /// <summary>
        /// 将 Icon 转换为 BitmapImage
        /// </summary>
        /// <param name="icon"></param>
        /// <returns></returns>
        private static System.Windows.Media.Imaging.BitmapImage ConvertIconToBitmapImage(System.Drawing.Icon icon)
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                // 将 Icon 保存到内存流中
                icon.Save(memoryStream);
                memoryStream.Seek(0, SeekOrigin.Begin);

                // 创建 BitmapImage
                System.Windows.Media.Imaging.BitmapImage bitmapImage = new System.Windows.Media.Imaging.BitmapImage();
                bitmapImage.BeginInit();
                bitmapImage.StreamSource = memoryStream;
                bitmapImage.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
                bitmapImage.EndInit();

                return bitmapImage;
            }
        }

        #endregion

    }
}
